<template>
  <div id="project-components">
    <!-- 整体进度条显示 -->
    <div id="comp-process">
      <span style="line-height: 26px; margin-left: 8px; float: left">构建进度：</span>
      <el-progress
        :stroke-width="15"
        :status="currentPercent === 100 ? 'success' : null"
        :percentage="currentPercent || 0"
      />
    </div>
    <el-tabs v-model="activeName" type="border-card" class="full-height-tabs" @tab-click="changeComp">
      <el-tab-pane
        v-for="tabIndex in tabData"
        :key="tabIndex.name"
        :label="tabIndex.label + '(' +tabIndex.compNum + ')'"
        :name="tabIndex.name"
      >
        <el-table
          id="component_table"
          :key="resizeKey"
          ref="compTblRef"
          :comp-pane-name="tabIndex.name"
          :data="componentTblData"
          max-height="570"
          border
          :header-cell-class-name="componentHeaderClassName"
          cell-class-name="componentInfoClassName"
          :row-class-name="setRowIndex"
          @selection-change="handleSelectionChange"
          @filter-change="calcCurNum"
        >
          <el-table-column
            type="selection"
            width="55"
            :selectable="checkStatus"
          />
          <template v-for="header in resetCompFilterHeaders">
            <el-table-column
              v-if="hiddenCompCell(header, activeName)"
              :key="header.prop"
              :prop="header.prop"
              :label="header.label"
              :width="header.width"
              :filters="header.filters || undefined"
              :filter-method="header.filterMethod"
            >
              <!-- 标签表头处理 -->
              <template slot="header">
                <span v-if="header.isBranch || header.isTag || header.isOp" v-html="header.label" />
                <span v-else-if="header.isTag">{{ header.label }}</span>
              </template>
              <template slot-scope="scope">
                <!-- 标记激活自动构建的组件 -->
                <div v-if="header.prop === 'componentName'">
                  <el-badge
                    :value="scope.row['enableAutoBuild'] === 1 ? 'Auto': ''"
                    class="component-name-item"
                    type="success"
                  >
                    <el-tag v-if="scope.row['enableAutoBuild'] === 1" size="medium" type="info">
                      {{ scope.row[header.prop] }}
                    </el-tag>
                    <span v-else>{{ scope.row[header.prop] }}</span>
                  </el-badge>
                </div>
                <!-- TAG下拉框和标签显示切换 -->
                <!-- 分支或者Tag -->
                <div v-else-if="header.isBranch || header.isTag">
                  <div v-if="!scope.row.clickShow">
                    <el-tag
                      size="mini"
                      :type="activeName === 'frontend'? 'success': 'warning'"
                      :class="dynamicBuildRes(scope.row, buildStepProgress).taskTips.isDone? '' : 'disabled-tag'"
                    >
                      <span
                        :class="dynamicBuildRes(scope.row, buildStepProgress).taskTips.isDone? '' : 'disabled-tag-span'"
                        @click="changeEl(scope.row, 'tag')"
                      >
                        {{ scope.row[header.prop] }}
                      </span>
                    </el-tag>
                    <el-tooltip
                      v-if="scope.row[header.prop] === '-'"
                      effect="dark"
                      content="组件基于主分支更新，当前已是最新版本"
                      placement="top-start"
                    >
                      <el-button type="text" icon="iconfont icon-wenhao" size="mini" />
                    </el-tooltip>
                  </div>
                  <el-select
                    v-else
                    :ref="scope.row.id"
                    v-model="scope.row.branchTag"
                    :comp-pane-name="tabIndex.name"
                    size="mini"
                    filterable
                    placeholder="请选择"
                    @change="changeEl(scope.row, 'select')"
                    @visible-change="recoverToTag"
                  >
                    <el-option
                      v-for="option in scope.row.branchTagList"
                      :key="option.value"
                      :label="option.label"
                      :value="option.value"
                    />
                  </el-select>
                </div>
                <!-- 运行状态 -->
                <div v-else-if="header.isStatus">
                  <span>
                    <el-tooltip
                      effect="dark"
                      :content="aliveExtraInfo(scope.row, projectStatus).statusTip"
                      placement="top-start"
                    >
                      <i class="iconfont" :class="aliveExtraInfo(scope.row, projectStatus).iconSrc" />
                    </el-tooltip>
                  </span>
                </div>
                <!-- 构建结果 -->
                <div v-else-if="header.isRes" id="build_res">
                  <span>
                    <el-tooltip
                      effect="dark"
                      :content="dynamicBuildRes(scope.row, buildStepProgress).taskTips.tip"
                      placement="top-start"
                    >
                      <i
                        v-if="!dynamicBuildRes(scope.row, buildStepProgress).taskTips.isRun"
                        class="iconfont"
                        :class="dynamicBuildRes(scope.row, buildStepProgress).taskTips.iconSrc"
                      />
                      <i v-else class="el-icon-loading" />
                    </el-tooltip>
                  </span>
                </div>
                <!-- 操作 -->
                <div v-else-if="header.isOp" id="build_op">
                  <div v-if="isAutoBuild">
                    <el-switch
                      v-model="scope.row['enableAutoBuild']"
                      active-text="激活"
                      inactive-text="关闭"
                      :active-value="1"
                      :inactive-value="0"
                      @change="activeAutoBuild($event, scope.row)"
                    />
                  </div>
                  <div v-else>
                    <el-button
                      size="mini"
                      type="text"
                      :disabled="!dynamicBuildRes(scope.row, buildStepProgress).taskTips.isDone"
                      @click="batchBuild(scope.row)"
                    >
                      <i class="iconfont icon-a-quickdeployment" />
                      快速构建
                    </el-button>
                    <el-button
                      size="mini"
                      type="text"
                      :disabled="!dynamicBuildRes(scope.row, buildStepProgress).taskTips.isDone"
                      @click="updateCompInfo(scope.row, scope.$index)"
                    >
                      <i class="iconfont icon-gengxin" />
                      编辑
                    </el-button>
                    <el-button size="mini" type="text" @click="compBuildDetail(scope.row)">
                      <i class="el-icon-more" />
                      更多
                    </el-button>
                  </div>
                </div>
                <span v-else>{{ scope.row[header.prop] }}</span>
              </template>
            </el-table-column>
          </template>
        </el-table>
      </el-tab-pane>
    </el-tabs>
    <div class="extra-button-class">
      <el-button size="mini" @click="clearCompFilter">
        清空过滤
      </el-button>
      <div v-if="!isAutoBuild" class="no-auto-set-div">
        <!-- 模式切换 -->
        <el-radio-group v-model="selectedMode" size="mini" @change="handleModeChange">
          <el-radio-button label="branch">分支模式</el-radio-button>
          <el-radio-button label="tag">TAG模式</el-radio-button>
        </el-radio-group>
        <el-button-group>
          <el-button
            type="primary"
            size="mini"
            :disabled="isAllowBatch"
            @click="batchBuild"
          >
            批量构建
          </el-button>
          <el-button
            size="mini"
            type="warning"
            :disabled="isAllowBatch"
            @click="batchOffline"
          >批量下线</el-button>
        </el-button-group>
        <el-button
          size="mini"
          @click="offlineList"
        >下线列表</el-button>
        <el-button
          size="mini"
          type="primary"
          @click="addComp"
        >新增组件</el-button>

        <el-button
          type="primary"
          size="mini"
          icon="iconfont icon-uwa_icon_automatic_detection"
          @click="autoBuildSet"
        >
          自动发版设置
        </el-button>
      </div>
      <div v-else class="no-auto-set-div">
        <el-button-group>
          <el-button
            size="mini"
            type="primary"
            :disabled="isAllowBatch"
            @click="batchAutoSet(true)"
          >批量激活</el-button>
          <el-button
            size="mini"
            type="info"
            :disabled="isAllowBatch"
            @click="batchAutoSet(false)"
          >批量关闭</el-button>
        </el-button-group>
        <el-button
          size="mini"
          type="danger"
          @click="cancelAutoSet"
        >取消设置</el-button>
        <el-tooltip class="item" effect="dark" content="说明：可以单个组件激活/关闭自动发版，或者勾选之后再批量设置" placement="top-start">
          <el-button type="text" icon="iconfont icon-wenhao" size="mini" />
        </el-tooltip>
      </div>
    </div>
    <!-- 编辑操作 -->
    <el-dialog
      v-if="componentVisible"
      v-draggable
      title="组件信息"
      :visible.sync="componentVisible"
      width="30%"
      :close-on-click-modal="false"
    >
      <ComponentEdit
        ref="compEditRef"
        :component-info="compInfo"
        :cur-comp-name="activeName"
        :operate-type="operateType"
        @edit-cancel="editCancel"
        @edit-submit="editSubmit"
        @fetch-tags="selectBranchTag"
        @flush-comps="flushComps"
      />
    </el-dialog>
    <!-- 组件构建详情 -->
    <el-dialog
      v-if="buildDetailVisible"
      v-draggable
      :title="'构建详情（' + compInfo.name + '）'"
      :visible.sync="buildDetailVisible"
      width="50%"
      :close-on-click-modal="false"
    >
      <ComponentDetail
        v-if="isDataLoaded"
        :component-info="compInfo"
        @detail-config-cancel="detailConfigCancel"
        @detail-config-build="detailConfigBuild"
      />
    </el-dialog>

    <!-- 已下线列表 -->
    <el-dialog
      v-if="offlineVisible"
      v-draggable
      title="已下线组件列表"
      :visible.sync="offlineVisible"
      width="50%"
      :close-on-click-modal="false"
    >
      <OfflineCompList @submit-online="onlineSubmit" />
    </el-dialog>
  </div>
</template>
<script>
import { mapGetters } from 'vuex'
import ComponentEdit from '@/views/projectManage/projectList/component/ComponentEdit.vue'
import ComponentDetail from '@/views/projectManage/projectList/component/ComponentDetail.vue'
import OfflineCompList from '@/views/projectManage/projectList/component/OfflineCompList.vue'
import { compRunStatus } from '@/utils/utils'
import {
  getCompBranchTagList,
  queryProjectBuildProgress,
  getProjectComps,
  removeRealBuildLog,
  removePushRemoteProgress
} from '@/api/project'
import { upgradeComponent } from '@/api/task'
import { getGitProviderByManageId } from '@/api/gitProvider'
import { onOfflineComps, updateComponentInfo } from '@/api/component'

export default {
  name: 'ProjectComponents',
  components: { ComponentDetail, ComponentEdit, OfflineCompList },
  data() {
    return {
      componentList: {},
      selectedMode: 'tag',
      buildDetailVisible: false,
      isDataLoaded: false,
      activeName: this.$const.COMP_TYPE_KEY_FRONT,
      compPaneName: this.$const.COMP_TYPE_KEY_FRONT,
      compInfo: {},
      // 组件表头
      componentHeaders: [{
        prop: 'componentId',
        label: '组件ID',
        isHidden: true
      }, {
        prop: 'componentName',
        label: '组件名称',
        isFilter: true,
        filters: [],
        filterMethod: this.filterCompHandler
      }, {
        prop: 'remoteUrl',
        label: 'Git地址',
        isHidden: true
      }, {
        prop: 'branch',
        label: '🏷️ 组件分支<span style="font-size: 10px; color: #FF7272">（点击切换分支）</span><p style="font-size: 10px; color: #909399">分支与TAG互斥</p>',
        isBranch: true,
        isHidden: true
      }, {
        prop: 'tag',
        label: '🔀 组件TAG<span style="font-size: 10px; color: #FF7272">（点击切换TAG）</span><p style="font-size: 10px; color: #909399">分支与TAG互斥</p>',
        isTag: true
      }, {
        prop: 'supervisor',
        label: '负责人',
        isFilter: true,
        filters: [],
        filterMethod: this.filterCompHandler
      }, {
        prop: 'dirName',
        label: '目录命名'
      }, {
        prop: 'funcDesc',
        label: '功能描述'
      }, {
        prop: 'isCompiled',
        label: '是否编译',
        width: '90px',
        isFrontend: true,
        isFilter: true,
        filters: [],
        filterMethod: this.filterCompHandler
      }, {
        prop: 'dbName',
        label: '数据库名称',
        isBackend: true
      }, {
        prop: 'isPython',
        label: '是否为Python组件',
        isBackend: true,
        isFilter: true,
        filters: [],
        filterMethod: this.filterCompHandler
      }, {
        prop: 'status',
        label: '运行状态',
        isStatus: true,
        width: '90px',
        isFilter: true,
        filters: [],
        filterMethod: this.filterCompHandler,
        isBackend: true
      }, {
        prop: 'operation',
        label: '操作<p style="font-size: 10px; color: #909399">注：批量构建和快速构建以默认配置进行构建，不会弹出确认提示（包括：更新全部环境，激活所有步骤，JAVA组件更新SQL）</p>',
        isOp: true,
        width: '220px'
      }, {
        prop: 'buildRes',
        label: '构建结果',
        isRes: true,
        width: '90px',
        isFilter: true,
        filters: [],
        filterMethod: this.filterCompHandler
      }],
      componentTblData: [],
      tabData: [{
        name: this.$const.COMP_TYPE_KEY_FRONT,
        label: '前端组件',
        compNum: 0
      }, {
        name: this.$const.COMP_TYPE_KEY_BACK,
        label: '后端组件',
        compNum: 0
      }],
      isAllowBatch: true,
      clickShow: false,
      // 组件运行状态，通过websocket实时推送
      isRunAlive: {},
      // 构建结果，通过websocket实时推送，默认为初始化状态
      buildRes: {},
      currentPercent: 0,
      componentVisible: false,
      selectRow: [],
      isTagFetching: {},
      // 原始数据，点击获取tag时，先保存原始数据，当获取tag标签超时时，要恢复到原来的数据
      originalRow: {},
      isRemoving: false,
      resizeKey: 0,
      offlineVisible: false,
      operateType: this.$const.OPERATE_TYPE_ADD,
      isAutoBuild: false
    }
  },
  computed: {
    ...mapGetters([
      'projectStatus',
      'buildStepProgress',
      'compTagList',
      'buildStep'
    ]),
    // 表格列添加过滤
    resetCompFilterHeaders() {
      return this.componentHeaders.map(header => {
        if (!header.isFilter) {
          // 明确移除所有过滤相关属性，避免残留空配置
          const { ...rest } = header
          return rest
        }
        const prop = header.prop
        const uniqueVals = new Set()
        for (const index in this.componentTblData) {
          const compRow = this.componentTblData[index]
          const resCode = this.buildStepProgress[compRow.componentId] || compRow.lastUpdateStatus || this.$const.TASK_INFO_STOP
          compRow['buildRes'] = resCode === this.$const.TASK_INFO_INIT ? '初始化'
            : resCode === this.$const.TASK_INFO_DOING ? '执行中' : resCode === this.$const.TASK_INFO_SUCCESS
              ? '成功' : resCode === this.$const.TASK_INFO_FAILURE ? '失败' : resCode === this.$const.TASK_INFO_WAITING
                ? '等待中' : '待执行'
          const runStatus = compRunStatus(compRow.projectId, compRow.componentId, this.projectStatus)
          compRow['status'] = runStatus ? '运行正常' : '运行异常'
          this.componentTblData[index] = compRow
          const propVal = compRow[prop]
          if (!propVal) {
            continue
          }
          uniqueVals.add(propVal)
        }
        // 当切换tab页时，需要重置header.filters，避免不同组件之间的影响
        header.filters = []
        uniqueVals.forEach(e => header.filters.push({
          'text': e,
          'value': e
        }))
        // 确保过滤列配置正确的 filters 和 filterMethod
        return {
          ...header,
          filters: header.filters || [],
          filterMethod: header.filterMethod || ((value, row) => true)
        }
      })
    }
  },
  watch: {
    buildStepProgress: {
      immediate: true,
      handler(newVal) {
        if (newVal['projectId'] !== this.$route.meta.projectId) {
          this.currentPercent = 0
          return
        }
        this.dynamicPercent(newVal)
      }
    },
    buildStep: {
      immediate: true,
      deep: true,
      async handler(newVal) {
        for (const compId in newVal) {
          const stateStep = newVal[compId]
          if (!this.isRemoving && !this.buildDetailVisible &&
            (stateStep === this.$const.TASK_INFO_SUCCESS || stateStep === this.$const.TASK_INFO_FAILURE)) {
            this.isRemoving = true
            await removeRealBuildLog({ componentId: compId })
            await removePushRemoteProgress({ projectId: this.$route.meta.projectId, componentId: compId })
            this.isRemoving = false
          }
        }
      }
    }
  },
  async mounted() {
    const loading = this.$loading({
      lock: true,
      text: 'Loading',
      spinner: 'el-icon-loading',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    await this.fetchCompData()
    this.initTblData()
    this.initProgressAndBuildRes()
    loading.close()
  },
  created() {
    // 浏览器放大缩小事件
    this.$nextTick(() => {
      this.resizeFun()
      // this.resizeFun窗口变化执行的方法
      window.addEventListener('resize', this.resizeFun)
    })
  },
  beforeDestroy() {
    // 离开页面时删除该监听
    window.removeEventListener('resize', this.resizeFun)
  },
  methods: {
    autoBuildSet() {
      this.isAutoBuild = true
    },

    batchAutoSet(isActive) {
      this.executeAutoSet(this.selectRow, isActive)
    },

    executeAutoSet(selectRows, isActive) {
      const reqRows = []
      selectRows.forEach(row => {
        const cpRow = { ...row }
        cpRow.isCompiled = row.isCompiled === '是' ? '1' : '0'
        cpRow.isPython = row.isPython === '是' ? '1' : '0'
        if (isActive) {
          cpRow['enableAutoBuild'] = 1
        } else {
          cpRow['enableAutoBuild'] = 0
        }
        reqRows.push(cpRow)
      })
      updateComponentInfo({
        components: reqRows,
        isCompileConfigToAll: 0,
        operateType: this.$const.OPERATE_TYPE_EDIT
      }).then(res => {
        this.$message.success('操作成功')
        // 重置表格数据
        reqRows.forEach(item => {
          const rowIndex = this.componentTblData.findIndex(or => or.componentId === item.componentId)
          const cpItem = { ...item }
          cpItem.isCompiled = item.isCompiled === '1' ? '是' : '否'
          cpItem.isPython = item.isPython === '1' ? '是' : '否'
          this.$set(this.componentTblData, rowIndex, cpItem)
        })
      }).catch(err => {
        console.error(err)
        this.$message.error('操作失败')
      })
    },

    // 单个激活操作
    activeAutoBuild(val, row) {
      this.executeAutoSet([row], val === 1)
    },

    cancelAutoSet() {
      this.isAutoBuild = false
    },

    // 新增组件
    addComp() {
      this.operateType = this.$const.OPERATE_TYPE_ADD
      this.componentVisible = true
    },

    // 批量下线
    batchOffline() {
      const compIds = []
      this.selectRow.forEach(row => compIds.push(row.id))
      onOfflineComps({ compIds: compIds, activeType: 0 }).then(async res => {
        this.$message.success('操作成功')
        await this.changeComp()
      }).catch(err => {
        console.error(err)
        this.$message.error('操作失败！！')
      })
    },

    async onlineSubmit() {
      await this.changeComp()
      this.offlineVisible = false
    },

    // 下线列表
    offlineList() {
      this.offlineVisible = true
    },

    // 刷新表格数据
    async flushComps() {
      await this.changeComp()
      this.componentVisible = false
    },

    // 监听浏览器放大缩小的事件
    resizeFun() {
      // 重置key，重新渲染表格，解决浏览器缩小导致最后一行被遮盖，并且水平滚动条不出现的问题
      this.resizeKey = Math.random()
    },
    // 拉取组件数据
    async fetchCompData() {
      const compRes = await getProjectComps({ projectId: this.$route.meta.projectId })
      if (!compRes.data) {
        this.$message.error('获取组件信息失败')
        return
      }
      this.componentList = compRes.data
    },

    checkStatus(row, index) {
      return this.dynamicBuildRes(row, this.buildStepProgress).taskTips.isDone
    },
    // 分支和TAG模式切换
    handleModeChange() {
      const branchIndex = this.componentHeaders.findIndex(item => item.isBranch)
      const branch = this.componentHeaders.find(item => item.isBranch)
      const tagIndex = this.componentHeaders.findIndex(item => item.isTag)
      const tag = this.componentHeaders.find(item => item.isTag)
      if (this.selectedMode === 'tag') {
        branch.isHidden = true
        tag.isHidden = false
      } else {
        branch.isHidden = false
        tag.isHidden = true
      }
      this.$set(this.componentHeaders, branchIndex, branch)
      this.$set(this.componentHeaders, tagIndex, tag)
    },

    // 初始化表格数据
    initTblData() {
      const frontNum = this.componentList.filter(item => {
        return item.compType === this.$const.COMP_TYPE_FRONTEND
      }).length
      const backNum = this.componentList.length - frontNum
      this.flushTabDataNum(this.$const.COMP_TYPE_KEY_FRONT, frontNum)
      this.flushTabDataNum(this.$const.COMP_TYPE_KEY_BACK, backNum)
      // 组件类型，1：前端组件；2：后端组件；3：python组件
      this.componentTblData = this.getCompInfo(true, [1, 2, 3])
    },

    // 获取组件信息
    getCompInfo(isInit, curTypes) {
      const data = []
      const cpCompList = [...this.componentList]
      cpCompList.forEach(e => {
        const compType = e.compType
        if (!curTypes.includes(compType)) {
          return
        }
        // 初始化时只需要添加前端组件，减少数据加载
        if (isInit && compType !== this.$const.COMP_TYPE_FRONTEND) {
          return
        }
        e['componentName'] = e.name
        e['componentId'] = e.id

        // 处理tag或者分支为空的情况
        e['branch'] = !e.branch ? '-' : e.branch
        e['tag'] = !e.tag ? '-' : e['tag']

        const compObj = {
          ...e, clickShow: false, branchTagList: [{
            label: e.tag,
            value: e.tag
          }]
        }

        compObj.isPython = e.compType === this.$const.COMP_TYPE_PYTHON ? '是' : '否'
        compObj.isCompiled = e.isCompiled === 1 ? '是' : '否'
        data.push(compObj)
      })

      // 处理附加信息
      const tmpTblData = []
      data.forEach(e => {
        this.buildRes[e.componentId] = this.$const.TASK_INFO_STOP
        tmpTblData.push({ ...e })
      })
      return tmpTblData
    },

    // 初始化进度条和构建结果
    initProgressAndBuildRes() {
      queryProjectBuildProgress({ projectId: this.$route.meta.projectId }).then(res => {
        const progressInfo = res.data
        if (progressInfo) {
          this.dynamicPercent(progressInfo)
          this.$refs.compTblRef.forEach(item => {
            this.dynamicBuildRes(item['data'], progressInfo)
          })
        }
      }).catch(err => {
        console.error(err)
      })
    },

    // 动态进度条
    dynamicPercent(progressInfo) {
      // 计算实时进度
      // 3种场景：
      // 1、批量构建，每完成一个组件，进度为： 总数 - 已完成 / 总数
      // 2、单个构建，取组件step中的progress数值
      // 3、点击每个组件构建，整体为批量，中间存在时间差，则：
      // 3.1、当第一个组件的当前进度大于等于批量完成的进度，则保持当前进度不变，直到批量的整体进度大于当前进度；
      // 3.2、当第一个组件的当前进度小于批量完成的进度，则以批量完成进度为准
      const compStepInfos = progressInfo['compStepInfos']
      if (!compStepInfos) {
        this.currentPercent = 0
        return
      }
      if (compStepInfos.length === 1) {
        this.currentPercent = compStepInfos[0].progress
        return
      }
      // 查找进度为100的数量
      const completeNum = compStepInfos.filter(item => {
        return item.progress === 100
      }).length
      const totalPercent = Math.floor(completeNum / compStepInfos.length * 100)
      if (totalPercent > this.currentPercent) {
        this.currentPercent = totalPercent
      }
    },

    // 处理tabData的数量变化
    flushTabDataNum(tabName, compNum) {
      if (!tabName) {
        return
      }
      this.tabData.forEach(e => {
        if (e.name === tabName) {
          e.compNum = compNum
        }
      })
    },
    // 处理运行状态的附加信息
    aliveExtraInfo(row, stateProStatus) {
      const componentId = row.componentId
      this.isRunAlive[componentId] = compRunStatus(row.projectId, componentId, stateProStatus)
      return {
        isAlive: this.isRunAlive[componentId],
        iconSrc: row.isPython === '是' ? 'icon-Python' : this.isRunAlive[componentId] ? 'icon-huabanfuben' : 'icon-yunhangyichang',
        statusTip: row.isPython === '是' ? 'Python组件' : this.isRunAlive[componentId] ? '组件运行正常' : '组件运行异常',
        status: this.isRunAlive[componentId] ? '正常' : '异常'
      }
    },
    // 构建结果处理
    dynamicBuildRes(row, stateBuildProgress) {
      const componentId = row.componentId
      const compStepInfos = stateBuildProgress['compStepInfos']
      let compBuildResult
      if (!compStepInfos || !(compBuildResult = compStepInfos.find(item => item.compId === componentId))) {
        // 初始化状态返回上一次构建结果，若不存在则返回待执行
        if (!row.lastUpdateStatus) {
          return { taskTips: { tip: '任务待执行', iconSrc: 'icon-stop-circle', isDone: true }}
        }
        return row.lastUpdateStatus === 2
          ? { taskTips: { tip: '任务执行成功', iconSrc: 'icon-bushuchenggong', isDone: true }}
          : { taskTips: { tip: '任务执行失败', iconSrc: 'icon-bushushibai', isDone: true }}
      }
      // 组件步骤：0 <-> Init
      // 1，2，3，4，5, 9 <-> doing
      // 6 <-> success
      // 8 <-> failure
      // 7 <-> waiting
      let stateStep
      if ([1, 2, 3, 4, 5, 9].includes(compBuildResult.step)) {
        stateStep = this.$const.TASK_INFO_DOING
      } else if (compBuildResult.step === 6) {
        stateStep = this.$const.TASK_INFO_SUCCESS
      } else if (compBuildResult.step === 7) {
        stateStep = this.$const.TASK_INFO_WAITING
      } else if (compBuildResult.step === 8) {
        stateStep = this.$const.TASK_INFO_FAILURE
      } else {
        stateStep = this.$const.TASK_INFO_INIT
      }
      this.$store.commit('project/SET_BUILD_STEP', { componentId: componentId, stateStep: stateStep })
      return {
        taskTips: stateStep === this.$const.TASK_INFO_INIT ? {
          tip: '任务初始化',
          iconSrc: 'icon-xitongchushihua'
        }
          : stateStep === this.$const.TASK_INFO_DOING ? {
            tip: '任务执行中',
            iconSrc: 'icon-zhihangzhong1',
            isRun: true
          }
            : stateStep === this.$const.TASK_INFO_SUCCESS ? {
              tip: '任务执行成功',
              iconSrc: 'icon-bushuchenggong',
              isDone: true
            }
              : stateStep === this.$const.TASK_INFO_FAILURE ? {
                tip: '任务执行失败',
                iconSrc: 'icon-bushushibai',
                isDone: true
              } : stateStep === this.$const.TASK_INFO_WAITING
                ? {
                  tip: '任务等待中',
                  iconSrc: 'icon-daizhihang'
                } : { tip: '任务待执行', iconSrc: 'icon-stop-circle', isDone: true }
      }
    },
    // 隐藏组件列
    hiddenCompCell(headerItem, activeName) {
      if (headerItem.isHidden) {
        return false
      }

      if (headerItem.isRes) {
        return !this.isAutoBuild
      }

      if (activeName === this.$const.COMP_TYPE_KEY_FRONT) {
        return !headerItem.isBackend
      }
      return !headerItem.isFrontend
    },
    // 批量构建
    batchBuild(tblRow) {
      // 只重置已完成进度
      this.currentPercent = this.currentPercent === 100 ? 0 : this.currentPercent
      const projectId = this.$route.meta.projectId
      if (this.selectRow.length > 0) {
        // 批量构建时使用默认配置，选择全部环境，不执行SQL
        this.execBatchOp(projectId)
        // 执行完成清空所选行，防止误操作重复提交任务
        return
      }
      // 快速构建
      const compBuildInfos = [{
        componentId: tblRow.id,
        branchTag: tblRow.branchTag
      }]
      this.executeBuild({ isDefaultOp: 1, projectId: projectId, compBuildInfos: compBuildInfos })
    },
    // 组件设置相关参数构建
    detailConfigBuild(buildData) {
      this.executeBuild(buildData)
    },
    executeBuild(buildData) {
      const loading = this.$loading({
        lock: true,
        text: '任务初始化中',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })

      const compBuildInfos = buildData.compBuildInfos
      compBuildInfos.forEach(item => {
        // 开始构建，即将状态设为doing
        this.$store.commit('project/SET_BUILD_STEP', {
          componentId: item.componentId,
          stateStep: this.$const.TASK_INFO_DOING
        })
      })

      if (this.selectedMode === 'tag') {
        buildData.compBuildInfos.forEach(item => {
          item['tag'] = item.branchTag
        })
      } else {
        buildData.compBuildInfos.forEach(item => {
          item['branch'] = item.branchTag
        })
      }

      // 查询当前登录账号是否已经添加git凭证
      getGitProviderByManageId().then(res => {
        const providers = res.data
        if (providers && providers.length > 0) {
          upgradeComponent(buildData).then(res => {
            this.$message.success('构建成功，任务已开始执行')
            loading.close()
          }).catch(err => {
            console.error(err)
            this.$message.error('构建失败')
          })
        } else {
          this.$confirm('未检测到Git凭证，是否前往添加？', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            this.$router.push({ name: 'gitProvider' })
          })
        }
      }).catch(err => {
        console.error(err)
        this.$message.error('获取Git凭证失败')
      })
    },
    execBatchOp(projectId) {
      const compBuildInfos = []
      this.selectRow.forEach(e => {
        compBuildInfos.push({
          componentId: e.id,
          branchTag: e.branchTag
        })
      })
      this.$refs.compTblRef.find(item => item.$attrs['comp-pane-name'] === this.activeName).clearSelection()
      this.executeBuild({ isDefaultOp: 1, projectId: projectId, compBuildInfos: compBuildInfos })
    },
    // 构建详情
    async compBuildDetail(tblRow) {
      this.compInfo = tblRow
      this.isDataLoaded = true
      this.buildDetailVisible = true
    },
    // 清除所有过滤器
    clearCompFilter() {
      this.$refs.compTblRef.forEach(e => {
        if (e.$attrs['comp-pane-name'] === this.activeName) {
          e.clearFilter()
        }
      })
      this.calcCurNum()
    },

    // 组件表格列过滤操作
    filterCompHandler(value, row, column) {
      const property = column['property']
      return row[property] === value
    },

    // 重新计算表格当时数量
    calcCurNum() {
      this.$refs.compTblRef.forEach(e => {
        if (e.$attrs.compPaneName === this.activeName) {
          this.flushTabDataNum(this.activeName, e.store.states.data.length)
        }
      })
    },

    // 切换组件
    async changeComp() {
      const loading = this.$loading({
        lock: true,
        text: 'Loading',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })
      await this.fetchCompData()
      loading.close()
      this.compPaneName = this.activeName
      if (this.activeName === this.$const.COMP_TYPE_KEY_FRONT) {
        this.componentTblData = this.getCompInfo(false, [this.$const.COMP_TYPE_FRONTEND])
        return
      }
      this.componentTblData = this.getCompInfo(false, [this.$const.COMP_TYPE_BACKEND, this.$const.COMP_TYPE_PYTHON])
    },
    // 表头行类名
    componentHeaderClassName() {
      if (this.activeName === this.$const.COMP_TYPE_KEY_FRONT) {
        return 'frontendHeaderCell'
      }
      return 'backendHeaderCell'
    },
    // 处理表格选中
    handleSelectionChange(val) {
      this.$nextTick(() => {
        this.isAllowBatch = val.length <= 0
        this.selectRow = val
      })
    },

    // 切换元素，即显示分支或者tag下拉列表，还是已经选中之后切换成el-tag状态
    async changeEl(row, type) {
      const cpRow = { ...row }
      if (type === 'select') {
        cpRow.clickShow = false
        if (this.selectedMode === 'tag') {
          cpRow.tag = row.branchTag
        } else {
          cpRow.branch = row.branchTag
        }
        this.$set(this.componentTblData, row.index, cpRow)
        return
      }
      this.originalRow = JSON.parse(JSON.stringify(cpRow))

      await this.selectBranchTag(cpRow)
      this.$set(this.componentTblData, row.index, cpRow)
      await this.$nextTick()
      cpRow['clickShow'] = true
      this.$set(this.componentTblData, row.index, cpRow)
      await this.$nextTick()
      const select = this.$refs[row.id].find(item => item.$attrs['comp-pane-name'] === this.activeName)
      if (select) {
        select.$el.querySelector('.el-input__inner').click()
      }
    },
    // 当下拉列表消失时，恢复成el-tag样式
    async recoverToTag(val) {
      if (!val) {
        this.originalRow.clickShow = false
        this.$set(this.componentTblData, this.originalRow.index, this.originalRow)
        await this.$nextTick()
      }
    },

    // 选择标签
    async selectBranchTag(row) {
      row.branchTagList = []
      const componentId = row.componentId
      const cacheTagInfo = this.compTagList.find(item => item.componentId === componentId)
      if (this.isTagFetching[componentId]) {
        if (!cacheTagInfo || cacheTagInfo['branchTagList'].length === 0) {
          this.$message.warning('组件正在克隆代码，请稍候再重试！')
          return
        } else {
          this.isTagFetching[componentId] = false
          this.compTagList.splice(this.compTagList.findIndex(item => item.componentId === componentId), 1)
        }
      }

      const loading = this.$loading({
        lock: true,
        text: '拼命加载中',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })
      const listType = this.selectedMode === 'tag' ? 1 : 0
      const res = await getCompBranchTagList({ componentId: componentId, listType: listType })
      if (res.data.length === 0) {
        this.$message.warning('编译目录找不到组件代码，开始克隆中，请稍候再重试！')
        this.isTagFetching[componentId] = true
        loading.close()
        return
      }
      this.$store.commit('project/SET_COMP_TAG_LIST', res.data)
      res.data.forEach(item => {
        row.branchTagList.push({
          label: item,
          value: item
        })
      })
      this.compInfo['branchTagList'] = row.branchTagList
      loading.close()
    },

    // 更新组件信息
    updateCompInfo(tblRow, rowIndex) {
      this.operateType = this.$const.OPERATE_TYPE_EDIT
      this.componentVisible = true
      this.compInfo = { ...tblRow }
      this.compInfo['rowIndex'] = rowIndex
      this.compInfo['selectedMode'] = this.selectedMode
      this.compInfo.isCompiled = this.compInfo.isCompiled === '是' ? '1' : '0'
      this.compInfo.isPython = this.compInfo.isPython === '是' ? '1' : '0'
    },

    // 编辑取消
    editCancel(val) {
      this.componentVisible = val
    },

    // 编辑提交
    async editSubmit() {
      const compRes = await getProjectComps({ projectId: this.$route.meta.projectId })
      if (!compRes.data) {
        this.$message.error('获取组件信息失败')
        return
      }
      this.componentList = compRes.data
      this.componentVisible = false
      this.activeName = 'frontend'
      this.initTblData()
    },

    setRowIndex({ row, rowIndex }) {
      // 设置行索引‌
      row.index = rowIndex
    },

    detailConfigCancel() {
      this.buildDetailVisible = false
    }
  }
}
</script>
<style>
#component_table .frontendHeaderCell {
  background-color: #C9E4C4;
  color: #000;
  text-align: center;
  border: 1px solid #EDEDED;
}

#component_table .backendHeaderCell {
  background-color: #7CDED7;
  color: #000;
  text-align: center;
  border: 1px solid #EDEDED;
}

#component_table .componentInfoClassName {
  text-align: center;
  font-size: 14px;
}

.icon-huabanfuben {
  color: #00CD66;
}

.icon-yunhangyichang {
  color: #FF7272;
}

.icon-xitongchushihua {
  color: #8B8B7A;
}

.icon-bushuchenggong {
  color: #00CD66;
}

.icon-bushushibai {
  color: #FF7272;
}

.icon-Python {
  color: #00756E;
}

#build_res .el-icon-loading {
  color: #5093D0;
}

.icon-daizhihang {
  color: #F99D3A;
}

.icon-gengxin {
  color: #4ACBEA;
}

.icon-a-quickdeployment {
  color: #4E6070;
}

.icon-xiangqing {
  color: #389BFF;
}

#comp-process {
  width: 100%;
  height: 36px;
}

#comp-process div[role="progressbar"] {
  margin-left: 95px !important;
  line-height: 26px;
}

.disabled-tag {
  cursor: not-allowed; /* 鼠标样式变为禁止点击 */
}

.disabled-tag-span {
  pointer-events: none; /* 禁用鼠标事件 */
  opacity: 0.6; /* 降低透明度，看起来像是被禁用 */
}

/* 处理el-tabs高度 */
.full-height-tabs {
  height: 100% !important;
}

#project-components {
  width: 100%;
  margin: 0 auto;
  position: relative;
}

.extra-button-class {
  width: 99%;
  position: absolute;
  top: 40px;
  left: 255px;
  display: flex;
  gap: 10px;
  align-items: center;
}

.no-auto-set-div{
  display: flex;
  gap: 10px;
  align-items: center;
}

.component-name-item {
  margin-top: 10px;
}
</style>
